#include <memory>
#include <utility>
#include <QFile>
#include <QTextStream>
#include <QStringList>
#include <QVector>
#include <QByteArray>
#include <QObject>
#include <QString>
#include <QMutex>
#include <QMutexLocker>
#include <QWaitCondition>
#include "ConsumerWorker.h"
#include "Utils/WaitUtils.h"
#include "InterruptedException.h"

ConsumerWorker::ConsumerWorker(const QString &dirName, const QString &firstSN, const QString &tail, int pixelNumbers, AvsMeasResultList *measuredData, QMutex *measMutex, QWaitCondition *measCondition, bool *stop)
    : _dirName(dirName), _firstSN(firstSN), _tail(tail), _pixelNumbers(pixelNumbers), _measuredData(measuredData), _measMutex(measMutex), _measCondition(measCondition), _stop(stop)
{

}

void ConsumerWorker::process1()
{
    try
    {
        FileUtils::CreateDir(_dirName);
        QString fileName = QString("%1_%2").arg(_firstSN).arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmss"));
        QString filePath = QString("%1/%2_temp.csv").arg(_dirName).arg(fileName);
        QString filePathResult = QString("%1/%2.csv").arg(_dirName).arg(fileName);

        QFile file(filePath);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        {
            qDebug() << "open file fail";
            return;
        }

        QTextStream out(&file);

        bool outputWavelength = true;
        while (true)
        {
            {
                QMutexLocker locker(_measMutex);
                while (_measuredData->isEmpty() && !_stop)
                {
                    _measCondition->wait(locker.mutex());
                }
            }
            if (*_stop && _measuredData->isEmpty())
            {
                break;
            }
           
            if (!_measuredData->isEmpty())
            {
                AvsMeasResult data;
                {
                    QMutexLocker locker(_measMutex);
                    data = _measuredData->takeFirst();
                }
                int count = data.resultData.count();
                if (outputWavelength)
                {
                    for (int i = 0; i < count; i++)
                    {
                        out << data.resultData.at(i).x();
                        QString end = (i == (count - 1)) ? "\n" : ",";
                        out << end;
                    }
                    outputWavelength = false;
                }
                for (int i = 0; i < count; i++)
                {
                    out << data.resultData.at(i).y();
                    QString end = (i == (count - 1)) ? "\n" : ",";
                    out << end;
                }
            }
        }
        file.close();

        transposeCsv(filePath, filePathResult);

        emit finished();

        QString message = QString("%1_temp.csv save successfully").arg(fileName);
        emit processingFinished(message);
    }
    catch (...)
    {
        emit finished();
        QString message = QString("Save fail");
        emit processingFinished(message);
    }
}

void ConsumerWorker::process()
{
    try
    {
        FileUtils::CreateDir(_dirName);
        QString fileName = QString("%1_%2%3").arg(_firstSN).arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmss")).arg(_tail);
        QString tempDir = QString("%1/%2%3").arg(_dirName).arg(fileName).arg(_tail);
        FileUtils::CreateDir(tempDir);
        QString filePathResult = QString("%1/%2.csv").arg(_dirName).arg(fileName);

        QVector<QFile*> tempFiles(_pixelNumbers);
        QVector<QTextStream*> tempStreams(_pixelNumbers);
        QVector<QVector<double>> buffers(_pixelNumbers); // 缓冲区数组

        for (int i = 0; i < _pixelNumbers; i++)
        {
            QString tempFilePath = QString("%1/row_%2.txt").arg(tempDir).arg(i);
            tempFiles[i] = new QFile(tempFilePath);
            if (!tempFiles[i]->open(QIODevice::WriteOnly | QIODevice::Text)) {
                qWarning("Cannot open temporary file for writing.");
                return;
            }
            QTextStream* stream = new QTextStream(tempFiles[i]);
            tempStreams[i] = stream;
            buffers[i] = QVector<double>(); // 初始化缓冲区
        }


        int count = 0;
        try
        {
            bool outputWavelength = true;
            while (true)
            {
                {
                    QMutexLocker locker(_measMutex);
                    while (_measuredData->isEmpty() && !_stop)
                    {
                        _measCondition->wait(locker.mutex());
                    }
                }
                if (*_stop && _measuredData->isEmpty())
                {
                    break;
                }

                if (!_measuredData->isEmpty())
                {
                    AvsMeasResult data;
                    {
                        QMutexLocker locker(_measMutex);
                        data = _measuredData->takeFirst();
                    }
                    count = data.resultData.count();
                    if (outputWavelength)
                    {
                        for (int i = 0; i < count; i++)
                        {
                            *tempStreams[i] << data.resultData.at(i).x() << ",";
                        }
                        outputWavelength = false;
                    }

                    // 添加数据到缓冲区
                    for (int i = 0; i < count; i++)
                    {
                        buffers[i].append(data.resultData.at(i).y());
                    }

                    // 当缓冲区达到100条数据时，写入文件并清空缓冲区
                    if (buffers[0].size() >= 100)
                    {
                        for (int i = 0; i < count; i++)
                        {
                            for (double value : buffers[i])
                            {
                                *tempStreams[i] << value << ",";
                            }
                            tempStreams[i]->flush();
                            buffers[i].clear(); // 清空缓冲区
                        }
                    }
                }
            }

            // 写入剩余数据到文件
            for (int i = 0; i < count; i++)
            {
                if (!buffers[i].isEmpty())
                {
                    for (double value : buffers[i])
                    {
                        *tempStreams[i] << value << ",";
                    }
                }
            }
        }
        catch (...)
        {

        }

        // 5. 关闭所有临时文件
        for (int col = 0; col < count; ++col) {
            tempStreams[col]->flush();
            tempFiles[col]->close();
            delete tempStreams[col];
            delete tempFiles[col];
            tempStreams[col] = nullptr;
            tempFiles[col] = nullptr;
        }



        // 6. 打开输出文件
        QFile outputFile(filePathResult);
        if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
            qWarning("Cannot open output file for writing.");
            return;
        }
        QTextStream out(&outputFile);

        // 7. 合并所有临时文件生成最终的转置文件
        for (int col = 0; col < count; ++col) {
            QString tempFilePath = QString("%1/row_%2.txt").arg(tempDir).arg(col);
            QFile tempFile(tempFilePath);
            if (!tempFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
                qWarning("Cannot open temporary file for reading.");
                continue;
            }
            QTextStream inTemp(&tempFile);
            QString line = inTemp.readLine();
            if (!line.isEmpty())
            {
                line = line.remove(line.lastIndexOf(','), 1).append("\n");
                out << line;
            }
            tempFile.close();
            tempFile.remove(); // 删除临时文件
        }
        QDir dir(tempDir);
        dir.rmdir(tempDir);

        // 8. 保存新文件
        outputFile.close();
        QString message = QString("%1.csv save successfully").arg(fileName);
        emit processingFinished(message);
        emit finished();

    }
    catch(InterruptedException)
    {
        QString message = QString("Save fail: Interrupted");
        emit processingFinished(message);
        emit finished();
    }
    catch (const std::exception& e)
    {
        QString message = QString("Save fail: %1").arg(e.what());
        qWarning() << "Exception caught:" << message;
        emit processingFinished(message);
        emit finished();
    }
    catch (...)
    {
        QString message = QString("Save fail: Unknown exception");
        qWarning() << "Unknown exception caught";
        emit processingFinished(message);
        emit finished();
    }
}

void ConsumerWorker::transposeCsv(const QString &inputFilePath, const QString &outputFilePath) {
    // 1. 读取原文件，确定行数和列数
    QFile inputFile(inputFilePath);
    if (!inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qWarning("Cannot open input file for reading.");
        return;
    }

    QTextStream in(&inputFile);
    QString firstLine = in.readLine();
    int N = firstLine.split(',').size(); // 列数
    int M = 1; // 行数，初始值为1（已经读取了第一行）

    while (!in.atEnd()) {
        in.readLine();
        ++M;
    }

    inputFile.seek(0); // 重置文件指针到开头
    in.setDevice(&inputFile);

    // 2. 建立索引，保存将要写入的文件的每一行的结尾在文件中的位置
    QVector<qint64> index(N, 0); // 初始化索引，所有位置设为0

    // 3. 打开输出文件
    QFile outputFile(outputFilePath);
    if (!outputFile.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
        qWarning("Cannot open output file for writing.");
        return;
    }

    // 4. 循环读取原文件的每一行，按逗号分隔符拆分每一个数据
    for (int row = 0; row < M; ++row) {
        QString line = in.readLine();
        QStringList values = line.split(',');

        // 5. 把每一个数据分别写入新文件的每一行，并且更新索引的位置
        for (int col = 0; col < N && col < values.size(); ++col) {

            //QByteArray data = values[col].toUtf8();
            QString value = values[col];
            QString signal = "";
            // 根据当前列和行的位置决定是否添加逗号或回车换行符
            if (row < M - 1) {
                //data.append(",");
                signal = ",";
            } else {
                //data.append("\n");
                signal = "\n";
            }
            QString str = QString("%1%2").arg(value).arg(signal);
            QByteArray data =str.toUtf8();
            qint64 dataSize = data.size();
            qDebug() << str << " " << dataSize;

            outputFile.seek(index[col]); // 移动到当前行的结尾位置
            outputFile.write(data); // 写入数据和分隔符

            // 更新当前列及其所有后续列的索引位置
            for (int j = col; j < N; ++j) {
                index[j] += dataSize;
            }

        }
    }

    // 7. 保存新文件
    inputFile.close();
    outputFile.close();
}
